package com.hu.hrm.service.impl;

import com.hu.hrm.constants.MQConstants;
import com.hu.hrm.domain.Pager;
import com.hu.hrm.feignclients.FastdfsFeignClient;
import com.hu.hrm.feignclients.RedisFeignClient;
import com.hu.hrm.mapper.PagerMapper;
import com.hu.hrm.mapper.SiteMapper;
import com.hu.hrm.service.IPagerService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.hu.hrm.util.AjaxResult;
import com.hu.hrm.util.MyFileUtils;
import com.hu.hrm.util.ZipUtils;
import com.hu.hrm.utils.VelocityUtils;
import com.alibaba.fastjson.JSON;
import org.junit.Test;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author woo
 * @since 2020-02-27
 */
/**分析 ： 页面静态化逻辑 需要完成哪些任务：
 1.判断 基本参数（pageName 和 Key ）

 2.下载准备模板==========================================
 2.1.根据PageName查询Pager对象，找到下载路径
 2.2.根据Pager里面的路径，去Fastdfs下载模板
 由于写到磁盘的时候用到了
 把templateZipBytes写到磁盘 ：临时目录 , 要把“\” ,替换成 “/” , 不用，因为是自动获取的目录，不会有问题
 创建文件
 把byte下载到磁盘
 2.3.把下载的zip格式的模板解压 : C:\Users\ADMINI~1\AppData\Local\Temp\pagestatic

 3.准备填充数据======================================
 3.1.根据redisDataKey去Redis查询数据（treeData）
 3.2.zip解压的路径作为staticRoot参数的值

 4.合并模板==========================================
 4.1.数据和模板作为参数
 4.2.使用模板引擎合并模板成html

 5.推送html==========================================
 5.1.把html上传到Fastdfs ， 拿到上传路径
 5.2.集成MQ，往MQ发送消息内容：1.html的fastdfs的下载路径， 2.html需要拷贝到Nginx的物理路径
 routingkey是什么？站点的编号，
 */
@Service
public class PagerServiceImpl extends ServiceImpl<PagerMapper, Pager> implements IPagerService {

    @Autowired
    private FastdfsFeignClient fastdfsFeignClient ; //下载模板等

    @Autowired
    private RedisFeignClient redisFeignClient ;//Redis

    @Autowired
    private RabbitTemplate rabbitTemplate ;//往MQ发消息

    @Autowired
    private SiteMapper siteMapper ;



    //获取系统临时目录 ：
    private String getTempDir(){
        String tempDir = System.getProperty("java.io.tmpdir");
        return tempDir;
    }
//    @Test
//    public void testdemo(){
//        System.out.println(System.getProperty("java.io.tmpdir"));
//    }         // C:\Users\51138\AppData\Local\Temp\


    //pageName:home
    @Override
    public void pageStatic(String pageName, String redisDataKey) throws Exception {
        System.out.println(pageName);
        //1.准备基本参数
        //参数判断
        if(!StringUtils.hasLength(pageName) || !StringUtils.hasLength(redisDataKey)){
            throw new RuntimeException("页面静态化失败，参数异常");
        }
        //2.根据PageName查询Pager对象
        Pager pager = baseMapper.selectByName(pageName);
        //通过Pager对象 里面中的路径，去Fastdfs下载模板
        System.out.println("模板下载路径："+pager.getTemplateUrl());
        byte[] templateZipBytes = fastdfsFeignClient.download(pager.getTemplateUrl());
        if(templateZipBytes == null || templateZipBytes.length == 0){
            throw new RuntimeException("下载模板失败");
        }
        //写道磁盘
        //确定模板下载成功后，应该把文件写到磁盘上了！  （路径比较重要）考虑到跨平台性，路径最好不写死
        //临时目录：（win cent都有的）  方法： System.getProperty("java.io.tmpdir");
        //然后把这个方法提出去 好看些

        //准备写入的路径（然后把文件写进去，可以有用，也可以用工具等等）  临时目录+pageName+后缀
        String zipPath = getTempDir()+pageName+".zip";
        System.out.println("模板文件写入："+zipPath);//C:\Users\51138\AppData\Local\Temp\home.zip

        //创建文件，注意：为了保证临时中有这个文件作为目的地，而使用的写入方法：拷贝，它没有自动创建没有的文件的功能，所以准备一个
        File zipFile = MyFileUtils.createFile(zipPath);

        //Spring提供工具（btye 考到文件中），把byte下载到磁盘
        FileCopyUtils.copy(templateZipBytes , zipFile);

        //下载的zip格式的模板解压  还是解压在临时目录里
        //之前是"pagestatic/" 但是说找不到，又拼接了一下成了下面的，然后static是模板文件夹的名字 （怀疑是解压工具的工作方式不同的问题）
        String unZipDir = getTempDir()+"pagestatic\\static/";
        System.out.println("模板解压路径: "+unZipDir);//C:\Users\51138\AppData\Local\Temp\pagestatic/
        ZipUtils.unZip(zipPath , unZipDir);//zipPath   输出的路径unZipDir

        //3.填充数据   根据redisDataKey去Redis查询数据（map)
        AjaxResult ajaxResult = redisFeignClient.get(redisDataKey);
        if(!ajaxResult.isSuccess() || ajaxResult.getResultObj() == null){
            throw new RuntimeException("数据获取失败");
        }

        //准备模板数据  从模板中 可预见需要的是一个集合 用于循环  而不是字符串，通过了解模板引擎 具体了解需要什么集合
        //可见最终在模板引擎中，需要将数据装到modle里面去的（准备了属性名，模板中能属性名点出来  就说明 可以准备个对象，准备的属性
        // 和模板中点的属性名一直即可嘛！）  其次考虑到map也可以！ 但是如果用对象的话又会比较麻烦，因为不确定那么多页面静态化属性名
        //避免频繁的封装对象，利用map来存  但是要注意：类型！！   如这里第一个放的List 第二个是路径放String就行了嘛
        //但是！ 页面静态化是公共的，针对一个页面 设定 明显不行，但是！ 那个服务要做静态化，它能确定唯一确定自己需要什么
        //即：谁调用谁写这一部分

        //参数1：
        //获取数据(每个微服务可能有对应)
        String dataString = ajaxResult.getResultObj().toString();
        //String -> Map
        Map<String,Object> model = JSON.parseObject(dataString,Map.class);


        //参数2 准备模板中需要的解压目录参数 staticRoot   分析可知： zip解压的路径即可作为staticRoot参数的值
        //如： unZipDir:C:\Users\Administrator\AppData\Local\Temp\pagestatic
        model.put("staticRoot",unZipDir);

        //4.合并模板  调用准的工具VelocityUtils 选择对应方法

        //模板  路径+名字+后缀（别写死 为好！）  这里有一个细节：约定（方便数据传送） 这里具体是：保存文件的时候把文件名和数据库中的
        //pageName对应了，这样 我们只需要直接拿pageName直接用就行了
        String templatePath = unZipDir+pageName+".vm";

        //合并后输出的路径  （即合成的html保存路径） ：现在还是先放在临时C:\Users\Administrator\AppData\Local\Temp\pagestatic\home.html
        String htmlPath = unZipDir+pageName+".html";

        //数据(准备的map 即model)   模板     合并后输出的路径
        VelocityUtils.staticByTemplate(model , templatePath ,htmlPath);

        //5.上传html 到Fastdfs
        //考虑到数据类型 如果用原来的方法 而重新封装比较麻烦，可以重新准备接口上传 （byte[]）

        //准备的是文件->byte  （和之间把byte->文件是差不多的）
        byte[] htmlBytes = FileCopyUtils.copyToByteArray(new File(htmlPath));

        AjaxResult htmlUploadResult = fastdfsFeignClient.uploadBytes(htmlBytes, "html");
        //判断： 走拖地 或 返回路径htmlUploadResult 是空的 那么久是失败
        if(!htmlUploadResult.isSuccess() || htmlUploadResult.getResultObj() == null){
            throw new RuntimeException("页面静态化失败，可能是合成的html上传失败");
        }

        //然后可以得到html在Fastdfs的路径
        String htmlPathInFastdfs = htmlUploadResult.getResultObj().toString();

       //5.2.集成MQ，往MQ发送消息
       // 需要：1.html的fastdfs的下载路径（即上面htmlPathInFastdfs）    2.html需要拷贝到Nginx的物理路径（pagger对象里面就存得有）
        //Nginx物理路径
        String physicalPath = pager.getPhysicalPath();
        //考虑到类型 准备了map
        Map<String,String > mqMessage = new HashMap<>();
        mqMessage.put("htmlPathInFastdfs",htmlPathInFastdfs);
        mqMessage.put("physicalPath",physicalPath);

        //巍峨了方便 约定了 routingkey : 当前pager对应的站点的sn.
        String routingKey =  siteMapper.selectById(pager.getSiteId()).getSn() ;

        //发送消息到MQ   交换机  routingKey   消息本身
        //转Json字符串给接受者，
        rabbitTemplate.convertAndSend(MQConstants.NAME_EXCHANGE_PAGE_DIRECT ,routingKey,JSON.toJSONString(mqMessage));

    }
}
